﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace GeoRef
{
    /// <summary>
    /// Represents white box tests of GeoRef classes
    /// </summary>
    [TestFixture]
    public class GeoPointWhiteBoxTests
    {
        GeoPoint point;
        GeoPoint p, q;
        /// <summary>
        /// Tests first argument range of object constructor,
        /// which accepts a pair of double
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestRangeFirstDouble(){        

            point = new GeoPoint(110, 11.3);

        }

        /// <summary>
        /// Tests second argument range of object constructor,
        /// which accepts a pair of double
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestRangeSecondDouble() {

            point = new GeoPoint(10, 191.3);            

        }

        /// <summary>
        /// Tests both arguments range of object constructor,
        /// which accepts a pair of double
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]        
        public void TestRangeBothDouble() {            

            point = new GeoPoint(110, -311.3);

        }

        /// <summary>
        /// Tests first argument range of object constructor,
        /// which accepts a string
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestRangeFirstString() {

            point = new GeoPoint("110, 11.3");

        }

        /// <summary>
        /// Tests second argument range of object constructor,
        /// which accepts a string
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestRangeSecondString() {

            point = new GeoPoint("10, 191.3");

        }

        /// <summary>
        /// Tests both arguments range of object constructor,
        /// which accepts a string
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestRangeBothString() {

            point = new GeoPoint("110, -311.3");

        }

        /// <summary>
        /// Tests the string overload object constructor
        /// behaviour, when passes it null
        /// </summary>
        [Test, ExpectedException(typeof(NullReferenceException))]
        public void TestNullArg() {
            point = new GeoPoint(null);
        }

        /// <summary>
        /// Tests the string overload object constructor
        /// behaviour, passing it a bad formed data
        /// </summary>
        [Test, ExpectedException(typeof(FormatException))]
        public void TestWrongFormatArg() {
            point = new GeoPoint("ciccio,pasticcio");
        }

        /// <summary>
        /// Tests "get" of all properties 
        /// </summary>
        [Test]
        public void TestGet() {
            Console.WriteLine("Well formed examples of GeoPoint object");
            point = new GeoPoint(43.4, 24.5);
            Assert.AreEqual(43.4, point.Lat);
            Assert.AreEqual(24.5, point.Lng);
            Console.WriteLine(point.ToString());

            point = new GeoPoint("23,54");
            Assert.AreEqual(23, point.Lat);
            Assert.AreEqual(54, point.Lng);
            Console.WriteLine(point.ToString());
        }

        /// <summary>
        /// Tests Lat property behaviour, trying to set an
        /// out of range value. It should catch an ArgumentOutOfRangeException
        /// exception.
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestSetLat1() {
            point = new GeoPoint(43.4, 24.5);
            point.Lat = 91;
            Console.WriteLine(point.ToString());
        }

        /// <summary>
        /// Tests Lat property behaviour, trying to set a
        /// correct value(-90 and 90).
        /// </summary>
        [Test]
        public void TestSetLat2() {
            Console.WriteLine("Right values for Lat.set");
            point = new GeoPoint(43.4, 24.5);
            point.Lat = -1.2343242;
            Console.WriteLine(point.ToString());
        }

        /// <summary>
        /// Tests Lng property behaviour, trying to set an
        /// out of range value. It should catch an ArgumentOutOfRangeException
        /// exception. 
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestSetLng1() {
            point = new GeoPoint(43.4, 24.5);
            point.Lng = -291;
            Console.WriteLine(point.ToString());
        }

        /// <summary>
        /// Tests Lng property behaviour, trying to set a
        /// correct value (-180 and 180).
        /// </summary>
        [Test]
        public void TestSetLng2() {
            Console.WriteLine("Right values for Lng.set");
            point = new GeoPoint(43.4, 24.5);
            point.Lng = -81.6452;
            Console.WriteLine(point.ToString());
        }

        /// <summary>
        /// Tests == operator behaviour
        /// </summary>
        [Test]
        public void TestEqualOp (){            
            point = new GeoPoint(-3.01, 13.01);
            p = new GeoPoint(-3.01, 13.01);
            q = new GeoPoint(3.01, 13.01);
            Assert.IsTrue(p == point, "Equal points");
            Assert.IsFalse(q == point, "Different points");

        }

        /// <summary>
        /// Tests != operator behaviour
        /// </summary>
        [Test]
        public void TestDiffOp() {            
            point = new GeoPoint(-3.01, 13.01);
            p = new GeoPoint(5.01, 13.01);
            q = new GeoPoint(-3.01, 13.01);
            Assert.IsTrue(p != point, "Different points");
            Assert.IsFalse(q != point, "Equal points");

        }

        /// <summary>
        /// Tests Equals method
        /// </summary>
        [Test]
        public void TestEquals() {
            point = new GeoPoint(-3.01, 13.01);
            p = new GeoPoint(5.01, 13.01);
            q = new GeoPoint(-3.01, 13.01);
            Assert.AreEqual(point, q);
            Assert.AreNotEqual(point, p);

        }

    }
}
